package com.umfwechat.h5.controller.billDetail;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.umfwechat.common.code.RetCode;
import com.umfwechat.common.constant.CacheConsts;
import com.umfwechat.util.DateTimesUtil;
import com.umfwechat.util.EmailXmlUtil;
import com.umfwechat.util.PropertyUtil;
import com.umfwechat.util.RedisUtil;
import com.umfwechat.util.ReqMessageUtil;
import com.umfwechat.util.SettleDirFilter;
import com.umfwechat.util.StringUtil;
import com.umfwechat.util.TimePathUtil;
import com.umfwechat.util.ZipUtil;
import com.umfwechat.util.email.MailSenderInfo;
import com.umfwechat.util.email.SendMailUtil;
import com.umpay.sp.model.common.ReqMessage;
import com.umpay.sp.model.common.ResMessage;
import com.umpay.sp.model.saas.StoreInf;
import com.umpay.sp.model.settle.SettleStat;
import com.umpay.sp.service.saas.remote.StoreInfServiceRemote;
import com.umpay.sp.service.settle.remote.SettleStatServiceRemote;
import com.umpay.sp.util.AmountUtil;
import com.umpay.sp.xml.XmlData;

/**
 * @ClassName MonthBillController
 * @desc 月账单
 * @author liuchunyan
 * @date 2017-05-19 下午 6:58:18
 * @version 1.0
 */
@Controller
@RequestMapping("/h5/billDetail")
public class MonthBillController {
	private static Logger logger = LoggerFactory.getLogger(MonthBillController.class);

	//结算查询
	@Resource
	private SettleStatServiceRemote settleStatServiceRemote;
	
	//店铺部署详情列表接口
	@Resource
	private StoreInfServiceRemote storeInfServiceRemote;
	
	private String yyyyMM = "yyyyMM";
	
	private int oneWeek = 7 * 24 * 60 * 60; //1周
	
	//邮件内容模板
	String templateEmailUrl = PropertyUtil.getProperties("umfWeChatPlat_appConf.properties").getProperty("templateEmailUrl");
	String noFileTemplateEmailUrl = PropertyUtil.getProperties("umfWeChatPlat_appConf.properties").getProperty("noFileTemplateEmailUrl");
	//文件打包路径
	String zipdownload = PropertyUtil.getProperties("umfWeChatPlat_appConf.properties").getProperty("zipdownload");
	//日结算文件路径
	String excelPath = "";
	
	/**
	 * desc:商户月账单列表查询
	 * 
	 * @param reqMessage
	 * @return ResMessage
	 * @throws 
	 * 	 */
	@RequestMapping(value="/getMonthBillList",produces="text/html;charset=UTF-8")
	@ResponseBody
	public String getMonthBillList(HttpServletRequest request, HttpServletResponse response){
		logger.info("商户月账单列表查询接口 开始");
		String storeId = request.getParameter("storeId");
		String pageSizeStr = request.getParameter("pageSize");
		String currentPageStr = request.getParameter("currentPage");
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<String> resultList = new ArrayList<String>();
		
		if(StringUtil.isEmpty(storeId)){
			logger.info("店铺编号不能为空！"); 
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "店铺编号不能为空！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(pageSizeStr) 
				|| Integer.parseInt(pageSizeStr) == 0){
			logger.info("每页条数必须大于0！");
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "每页条数必须大于0！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(currentPageStr) 
				|| Integer.parseInt(currentPageStr) == 0){
			logger.info("当前页数必须大于0！");
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "当前页数必须大于0！");
			return JSONObject.fromObject(resultMap).toString();
		}
		
		try{
			int currentPage = Integer.parseInt(currentPageStr);
			int pageSize = Integer.parseInt(pageSizeStr);
			
			//当前时间
			Calendar calendar = Calendar.getInstance();
			String currentDateStr =  DateTimesUtil.date8(calendar.getTime());

			//最近1年
			Calendar preYearCalendar = Calendar.getInstance();
			preYearCalendar.add(Calendar.YEAR, -1);
			preYearCalendar.add(Calendar.MONTH, 1);
			preYearCalendar.set(Calendar.DATE, 1);
			String minDateStr = DateTimesUtil.date8(preYearCalendar.getTime());
			
			String currentStr = "";
			String endSettleYm = "";
			Calendar calendarYm = Calendar.getInstance();
			String calendarYmStr = DateTimesUtil.formatDate(calendarYm.getTime(), yyyyMM);
			int loopCnt = 0;
			if(currentPage == 1){//当月账单，调用结算查询接口
				calendar.set(Calendar.DATE, 1);
				String currFirstDate =  DateTimesUtil.date8(calendar.getTime());
				
				//结算查询
		        Map<String, Object> qryMap = new HashMap<String, Object>();
				qryMap.put("merId", storeId);//商户编号
				qryMap.put("endDate", currentDateStr);//结束时间
				qryMap.put("startDate", currFirstDate);//开始时间
				qryMap.put("dealState", "2"); //处理完成
				logger.info("结算查询 qryMap=" + qryMap);
				List<SettleStat> settleStatList = settleStatServiceRemote.querySettleStats(qryMap);
				
				Map<String, Object> dataMap = new HashMap<String, Object>();
				dataMap.put("yearMonth", currentDateStr.substring(0, 6));
				if(settleStatList == null || settleStatList.size() == 0){
					dataMap.put("successAmt", "0.00");
				}else{
					//按月统计
					Long amount = 0L;
					for(SettleStat settleStat : settleStatList){
						amount = amount + settleStat.getAmount();
					}
					dataMap.put("successAmt", AmountUtil.Cent2Dollar2(amount));//分转元
				}
				currentStr = JSONObject.fromObject(dataMap).toString();
				resultList.add(currentStr);
				loopCnt = pageSize - 1;
				endSettleYm = DateTimesUtil.addMonths(calendarYmStr, -1);
				calendarYm.add(Calendar.MONTH, -1);
			}else{
				loopCnt = pageSize;
				int months = -(currentPage-1) * loopCnt;
				endSettleYm = DateTimesUtil.addMonths(calendarYmStr, months);
				calendarYm.add(Calendar.MONTH, months);
			}
			
			//查询缓存
			boolean redisNotExsitFlg = false;
			//查看
			boolean maxViewFlg = false;
			boolean hasNextData = false;
			
			for(int i=0; i<loopCnt; i++){
				String yearMonth = DateTimesUtil.addMonths(endSettleYm, -i);
				if(yearMonth.compareTo(minDateStr.substring(0,6)) < 0){
					maxViewFlg = true;
					break;
				}
				String redisKey = CacheConsts.WX + CacheConsts.MONTHBILL + storeId + yearMonth;
				String redisVal = RedisUtil.get(redisKey);
				if(StringUtil.isEmpty(redisVal)){ //缓存中不存在
					redisNotExsitFlg = true;
					break;
				}
				//订单信息添加到日统计列表
				resultList.add(redisVal);
			}
			
			//最多能看 或者 缓存存在
	        if(maxViewFlg || !redisNotExsitFlg){
	        	logger.info("获取月账单成功！");
	        	resultMap.put("retCode", RetCode.SUC);
	    		resultMap.put("retMsg", "获取月账单成功！");
	    		resultMap.put("hasNextData", hasNextData);
	    		resultMap.put("resultList", resultList);
	    		return JSONObject.fromObject(resultMap).toString();
	        }
	        
	        //初期化列表
	        resultList = new ArrayList<String>();
			if(!StringUtil.isEmpty(currentStr)){
				resultList.add(currentStr);	
			}
			
	        //结算查询
			String endSettleDate = endSettleYm + DateTimesUtil.getMaxDaysOfMonth(endSettleYm);
			String startSettleDate = DateTimesUtil.addMonths(endSettleYm, -loopCnt + 1) + "01";
	        Map<String, Object> qryMap = new HashMap<String, Object>();
			qryMap.put("merId", storeId);//商户编号
			qryMap.put("endDate", endSettleDate);//结束时间
			qryMap.put("startDate", startSettleDate);//开始时间
			qryMap.put("dealState", "2"); //处理完成
			logger.info("结算查询 qryMap=" + qryMap);
			List<SettleStat> settleStatList = settleStatServiceRemote.querySettleStats(qryMap);
			
			//下一页是否有数据
			Map<String, Object> qryMapNext = new HashMap<String, Object>();
			qryMapNext.put("merId", storeId);//商户编号
			qryMapNext.put("endDate", DateTimesUtil.addMonths(startSettleDate, -1));//结束时间
			qryMapNext.put("startDate", minDateStr.substring(0,6));//开始时间
			qryMapNext.put("dealState", "2"); //处理完成
			logger.info("结算查询(下一页是否有数据) qryMapNext=" + qryMapNext);
			List<SettleStat> settleStatListNext = settleStatServiceRemote.querySettleStats(qryMapNext);
			
			if(settleStatListNext != null && settleStatListNext.size() > 0){
				hasNextData = true;
			}
			//按月统计
			List<SettleStat> newSettleStatList = new ArrayList<SettleStat>();
			if(settleStatList != null && settleStatList.size()>0){
				for(SettleStat settleStat : settleStatList){
					boolean isOld = false;
					String settleStatYm = settleStat.getSettleDate().substring(0,6);
					for(SettleStat newSettleStat : newSettleStatList){
						//相同年月
						if(settleStatYm.equals(newSettleStat.getSettleDate().substring(0,6))){
							//结算金额
							newSettleStat.setAmount(newSettleStat.getAmount() + settleStat.getAmount());
							isOld = true;
						}
					}
					if(!isOld){
						newSettleStatList.add(settleStat);
					}
				}
			}
			
			//编辑输出列表
			if(newSettleStatList.size() > 0 || hasNextData){
				for(int i=0; i<loopCnt; i++){
					String successAmt = "0.00";
					String yearMonth = DateTimesUtil.addMonths(endSettleYm, -i);
					for(SettleStat settleStat : newSettleStatList){
						if(yearMonth.equals(settleStat.getSettleDate().substring(0,6))){
							successAmt = AmountUtil.Cent2Dollar2(settleStat.getAmount());//分转元
							break;
						}
					}
					Map<String, Object> dataMap = new HashMap<String, Object>();
					dataMap.put("yearMonth", yearMonth);
					dataMap.put("successAmt", successAmt);
					String dataStr = JSONObject.fromObject(dataMap).toString();
					resultList.add(dataStr);
					//添加到缓存
					String redisKey = CacheConsts.WX + CacheConsts.MONTHBILL + storeId + yearMonth;
					RedisUtil.set(redisKey, oneWeek, dataStr);
				}
			}
			
			logger.info("获取月账单成功！");
			resultMap.put("retCode", RetCode.SUC);
			resultMap.put("retMsg", "获取月账单成功！");
			resultMap.put("hasNextData", hasNextData);
			resultMap.put("resultList", resultList);
			return JSONObject.fromObject(resultMap).toString();
			
		} catch (Exception e) {
			logger.info("获取月账单失败",e);
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "获取月账单失败");
			return JSONObject.fromObject(resultMap).toString();
		}
	}
	
	/**
	 * desc:月账单月份列表
	 * 
	 * @param reqMessage
	 * @return ResMessage
	 * @throws 
	 * 	 */
	@RequestMapping(value="/getBillMonths",produces="text/html;charset=UTF-8")
	@ResponseBody
	public String getBillMonths(HttpServletRequest request, HttpServletResponse response){
		logger.info("月账单月份列表 开始");
		Calendar calendar = Calendar.getInstance();
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<String> resultList = new ArrayList<String>();
		for(int i = 0; i < 6; i++){
			if(i > 0){
				calendar.add(Calendar.MONTH, -1);
			}
			resultList.add(DateTimesUtil.date8(calendar.getTime()).substring(0,6));
		}
		logger.info("月账单月份列表成功！");
    	resultMap.put("retCode", RetCode.SUC);
		resultMap.put("retMsg", "月账单月份列表成功！");
		resultMap.put("resultList", resultList);
		return JSONObject.fromObject(resultMap).toString();
	}
	
	/**
	 * desc:发送月账单邮件
	 * 
	 * @param reqMessage
	 * @return ResMessage
	 * @throws 
	 * 	 */
	@RequestMapping(value="/sendBillEmail",produces="text/html;charset=UTF-8")
	@ResponseBody
	public String sendBillEmail(HttpServletRequest request, HttpServletResponse response){
		logger.info("发送月账单邮件 开始");
		final String merId = request.getParameter("merId");
		final String email = request.getParameter("email");
		final String billMonth = request.getParameter("billMonth");
			
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if(StringUtil.isEmpty(merId)){
			logger.info("主商户编号不能为空！"); 
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "主商户编号不能为空！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(email)){
			logger.info("邮箱地址不能为空！");
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "邮箱地址不能为空！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(billMonth)){
			logger.info("未选择账单月份！");
			resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "未选择账单月份！");
			return JSONObject.fromObject(resultMap).toString();
		}
		
		//店铺部署详情查询
		ReqMessage reqMessage = ReqMessageUtil.makeSpReq();
		reqMessage.put(XmlData.STORE_ID, merId);
		logger.info("店铺部署详情查询 reqMessage=" + reqMessage);
		ResMessage resMessage = storeInfServiceRemote.getStoreInfByPri(reqMessage);
		StoreInf storeInf = (StoreInf)resMessage.getValue(XmlData.STORE_INF);
		if(!resMessage.getRetCode().equals(RetCode.SUCCESS) || storeInf == null){
			logger.info("店铺部署详情查询失败！");
	    	resultMap.put("retCode", RetCode.FAIL);
			resultMap.put("retMsg", "店铺部署详情查询失败");
			return JSONObject.fromObject(resultMap).toString();
		}
		final String payeeName = storeInf.getPayeeName();

		// 新启动一个线程 发送邮件
		new Thread() {
			public void run(){
				logger.info("查找结算文件开始！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
				//获取结算日期集合
				List<String> settleDateList = getSettleDateList(billMonth);
				try {
					//文件路径集合
					List<String> dayFilePathList = getBatchFilePath(merId, settleDateList);
					boolean notExistsBoolean = true;
					if(dayFilePathList != null && dayFilePathList.size() > 0){
						for (String pathNameTmp : dayFilePathList) {
							File file = new File(pathNameTmp);
							if(file.exists()){
								notExistsBoolean = false;
							}
							file=null;
						}
					}
					if(notExistsBoolean){
						sendMail(noFileTemplateEmailUrl, email, payeeName, merId, billMonth, null);
						logger.info("结算文件还未生成邮件已发送，请查收！");
						return;
					}
					logger.info("查找结算文件结束！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
					
					logger.info("结算文件打包开始！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
					//文件打包
					File file = new File(zipdownload);//打包地址
					if (!file.exists()){
						file.mkdirs();
					}
					final String zipFileName = payeeName + "_" + merId + "_" + billMonth + ".zip";
					File zipFile = new File(zipdownload, File.separatorChar + zipFileName);
					//打包文件
					ZipUtil.zip(zipFile, dayFilePathList);
					logger.info("结算文件打包结束！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
					
					zipFile = new File(zipdownload + File.separatorChar + zipFileName);
					if (zipFile.exists()) {
						List<File> fileList = new ArrayList<File>();
						fileList.add(zipFile);
						//发邮件
						sendMail(templateEmailUrl, email, payeeName, merId, billMonth, fileList);
						logger.info("对账单邮件已发送，请查收！");
					}
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("发送邮件失败！" + e);
				}
			};
		}.start();
		
		logger.info("对账邮件将在3-5分钟后送达，请注意查收！");
    	resultMap.put("retCode", RetCode.SUC);
		resultMap.put("retMsg", "对账邮件将在3-5分钟后送达，请注意查收！");
		return JSONObject.fromObject(resultMap).toString();
	}
	
	/**
	 * 发送邮件
	 * 
	 * @param templateUrl 邮件内容模板
	 * @param email 收件邮箱
	 * @param payeeName 收款人姓名
	 * @param merId 主商户号
	 * @param billMonth 账单年月
	 * @param fileList 附件
	 */
	private void sendMail(String templateUrl, String email, String payeeName, String merId, String billMonth, List<File> fileList){
		logger.info("发送邮件开始！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
		Calendar calendar = Calendar.getInstance();
		String currentDate = DateTimesUtil.date8(calendar.getTime());
		//发邮件
		String mailto = email;
		String subject = payeeName + "_" + merId + "_" + billMonth + "电子对账单"; //收款人姓名_主商户号_账单月份电子对账单
		//邮件内容			
		Map<String, String> map = new HashMap<String, String>();
		map.put("payeeName", payeeName);
		map.put("merId", merId);
		map.put("billMonth", billMonth);
		map.put("YYYY", currentDate.substring(0,4));
		map.put("MM", currentDate.substring(4,6));
		map.put("DD", currentDate.substring(6,8));
		MailSenderInfo mailSenderInfo = new MailSenderInfo();
		mailSenderInfo.setToAddress(email);
		EmailXmlUtil.emailXmlRead(templateUrl, mailSenderInfo, map);
		String mailContent = mailSenderInfo.getContent();
		for (String s : map.keySet()) {
			mailContent = mailContent.replaceAll(s, map.get(s));
		}
		//发邮件
		if(fileList == null){
			SendMailUtil.sendMail(mailto, subject, mailContent);
		}else{
			SendMailUtil.sendMail(mailto, subject, mailContent, fileList);
		}
		logger.info("发送邮件结束！" + DateTimesUtil.date(DateTimesUtil.formatTime16Str));
	}
	
	/**
	 * 获取结算日期集合
	 * 
	 * @param billMonth 账单年月
	 * @return
	 */
	private List<String> getSettleDateList(String billMonth){
		Calendar calendar = Calendar.getInstance();
		String currentDate = DateTimesUtil.date8(calendar.getTime());
		int daysOfMonth = DateTimesUtil.getMaxDaysOfMonth(billMonth);
		List<String> settleDateList = new ArrayList<String>();
		String billMonthDay = billMonth + daysOfMonth;
		for(int i = 0 ; i<daysOfMonth; i++){
			String settleDate = DateTimesUtil.addDays(billMonthDay, -i);
			if(settleDate.compareTo(currentDate)>0){
				continue;
			}
			settleDateList.add(settleDate);
		}
		
		return settleDateList;
	}
	
	/**
	 * 文件路径集合
	 * @param merId 主商户号
	 * @param settleDateList 结算日期
	 * @return
	 * @throws ParseException
	 */
	private List<String> getBatchFilePath(String merId, List<String> settleDateList) throws ParseException{
		String excelPath = TimePathUtil.getTimePathWithXls(settleDateList.get(0), TimePathUtil.File.SETTLE);
		logger.info("日结算文件路径 excelPath ================ " + excelPath);
		List<String> fileNameList = new ArrayList<String>();
		for (int i = 0; i < settleDateList.size(); i++) {//对日期进行循环
			//过滤同时含有主商户号和日期的文件名
			SettleDirFilter settleDirFilter = new SettleDirFilter(merId, settleDateList.get(i));
			//获取文件列表
			String newPath = excelPath.replace(settleDateList.get(0), settleDateList.get(i));//文件存储路径
			File file = new File(newPath);
			String[] names = file.list(settleDirFilter);//路径下所有文件
			if(names != null){
				for (String name : names) {//遍历文件名，拼接路径和文件名
					String pathName = newPath + name;//拼接文件存储路径和文件名
					fileNameList.add(pathName);
				}
			}
		}
		return fileNameList;
	}
}